#创建一个trackbar：
    # 作用：通过滑动trackbar调整输入参数，获取更加合理的参数，调参更加直观和高效
    #每个算子都需要创建一个输入函数，待改进
    # 输入参数：img，图片源
    # 参数输入范围都0至255

import cv2
from graphics import *
import numpy as np
from dialogs import *

#定义一个无用的函数，不滑动trackbar时，跳过。
def nothing(arge):
    pass


#blur参数输入窗口
def blur_param(img,max):

    #创建一个带trackbar的窗口
    cv2.namedWindow('blur')
    cv2.createTrackbar('param','blur',1,max,nothing)

    while(1):
        try:
            ksize=cv2.getTrackbarPos('param','blur')
            if ksize<1:
                ksize=1

            blur_img=cv2.blur(img, (ksize, ksize), 1)
            cv2.imshow('blur',blur_img)
            k=cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k==27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize,blur_img
            elif cv2.getWindowProperty('blur',cv2.WND_PROP_AUTOSIZE)<1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break



#boxfiler参数输入窗口
def boxfiler_param(img,max):

    #创建一个带trackbar的窗口
    cv2.namedWindow('boxfiler')
    cv2.createTrackbar('param','boxfiler',1,max,nothing)

    while(1):
        try:
            ksize=cv2.getTrackbarPos('param','boxfiler')
            if ksize<1:
                ksize=1

            boxfiler_img=cv2.boxFilter(img,-1, (ksize, ksize))
            cv2.imshow('boxfiler',boxfiler_img)
            k=cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k==27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize,boxfiler_img
            elif cv2.getWindowProperty('boxfiler',cv2.WND_PROP_AUTOSIZE)<1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break




#Gaussian参数输入窗口
def Gaussian_param(img,max):

    #创建一个带trackbar的窗口
    cv2.namedWindow('Gaussian')
    cv2.createTrackbar('param','Gaussian',1,max,nothing)

    while(1):
        try:
            ksize=cv2.getTrackbarPos('param','Gaussian')
            ksize=2*ksize-1
            Gaussian_img=cv2.GaussianBlur(img, (ksize,ksize), 1)
            cv2.imshow('Gaussian',Gaussian_img)
            k=cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k==27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize,Gaussian_img
            elif cv2.getWindowProperty('Gaussian',cv2.WND_PROP_AUTOSIZE)<1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break


# median参数输入窗口
def median_param(img, max):
    # 创建一个带trackbar的窗口
    cv2.namedWindow('median')
    cv2.createTrackbar('param', 'median', 1, max, nothing)

    while (1):
        try:
            ksize = cv2.getTrackbarPos('param', 'median')
            ksize = 2 * ksize - 1
            if ksize < 1:
                ksize = 1
            median_img = cv2.medianBlur(img, ksize)
            cv2.imshow('median', median_img)
            k = cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k == 27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize, median_img
            elif cv2.getWindowProperty('median', cv2.WND_PROP_AUTOSIZE) < 1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break



# 二进制阀值化
def binary_param(img,max):

    #创建一个带trackbar的窗口
    cv2.namedWindow('binary')
    cv2.createTrackbar('param','binary',0,max,nothing)


    while(1):
        try:
            ksize=cv2.getTrackbarPos('param','binary')

            r,binary_img=cv2.threshold(img, ksize, 255,cv2.THRESH_BINARY)
            cv2.imshow('binary',binary_img)
            k=cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k==27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize,binary_img
            elif cv2.getWindowProperty('binary',cv2.WND_PROP_AUTOSIZE)<1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break



# 反二进制阀值化
def binary_inv_param(img,max):

    #创建一个带trackbar的窗口
    cv2.namedWindow('binary_inv')
    cv2.createTrackbar('param','binary_inv',0,max,nothing)

    while(1):
        try:
            ksize=cv2.getTrackbarPos('param','binary_inv')
            r,binary_inv_img=cv2.threshold(img, ksize, 255,cv2.THRESH_BINARY_INV)
            cv2.imshow('binary_inv',binary_inv_img)
            k=cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k==27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize,binary_inv_img
            elif cv2.getWindowProperty('binary_inv',cv2.WND_PROP_AUTOSIZE)<1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break



# 截断阀值化
def trunc_param(img,max):

    #创建一个带trackbar的窗口
    cv2.namedWindow('trunc')
    cv2.createTrackbar('param','trunc',0,max,nothing)

    while(1):
        try:
            ksize=cv2.getTrackbarPos('param','trunc')
            r,trunc_img=cv2.threshold(img, ksize, 255,cv2.THRESH_TRUNC)
            cv2.imshow('trunc',trunc_img)
            k=cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k==27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize,trunc_img
            elif cv2.getWindowProperty('trunc',cv2.WND_PROP_AUTOSIZE)<1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break



# 反阀值化为0
def tozero_param(img,max):

    #创建一个带trackbar的窗口
    cv2.namedWindow('tozero')
    cv2.createTrackbar('param','tozero',0,max,nothing)

    while(1):
        try:
            ksize=cv2.getTrackbarPos('param','tozero')
            r,tozero_img=cv2.threshold(img, ksize, 255,cv2.THRESH_TOZERO)
            cv2.imshow('tozero',tozero_img)
            k=cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k==27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize,tozero_img
            elif cv2.getWindowProperty('tozero',cv2.WND_PROP_AUTOSIZE)<1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break



# 阀值化为0
def tozero_inv_param(img,max):

    #创建一个带trackbar的窗口
    cv2.namedWindow('tozero_inv')
    cv2.createTrackbar('param','tozero_inv',0,max,nothing)

    while(1):
        try:
            ksize=cv2.getTrackbarPos('param','tozero_inv')
            r,tozero_inv_img=cv2.threshold(img, ksize, 255,cv2.THRESH_TOZERO_INV)
            cv2.imshow('tozero_inv',tozero_inv_img)
            k=cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k==27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize,tozero_inv_img
            elif cv2.getWindowProperty('tozero_inv',cv2.WND_PROP_AUTOSIZE)<1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break



# 开运算
def MORPH_OPEN_param( img, max):
    # 创建一个带trackbar的窗口
    cv2.namedWindow('MORPH_OPEN')
    cv2.createTrackbar('param', 'MORPH_OPEN', 1, max, nothing)

    while (1):
        try:
            ksize = cv2.getTrackbarPos('param', 'MORPH_OPEN')
            if ksize < 1:
                ksize = 1
            kernel = np.ones((ksize, ksize), np.uint8)
            MORPH_OPEN_img =cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
            cv2.imshow('MORPH_OPEN', MORPH_OPEN_img)
            k = cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k == 27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize, MORPH_OPEN_img
            elif cv2.getWindowProperty('MORPH_OPEN', cv2.WND_PROP_AUTOSIZE) < 1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break



# 闭运算
def MORPH_CLOSE_param(img, max):
    # 创建一个带trackbar的窗口
    cv2.namedWindow('MORPH_CLOSE')
    cv2.createTrackbar('param', 'MORPH_CLOSE', 1, max, nothing)

    while (1):
        try:
            ksize = cv2.getTrackbarPos('param', 'MORPH_CLOSE')
            if ksize < 1:
                ksize = 1
            kernel = np.ones((ksize, ksize), np.uint8)
            MORPH_OPEN_img =cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
            cv2.imshow('MORPH_CLOSE', MORPH_OPEN_img)
            k = cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k == 27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize, MORPH_OPEN_img
            elif cv2.getWindowProperty('MORPH_CLOSE', cv2.WND_PROP_AUTOSIZE) < 1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break



# 梯度运算
def GRADIENT_param(img, max):
    # 创建一个带trackbar的窗口
    cv2.namedWindow('GRADIENT')
    cv2.createTrackbar('param', 'GRADIENT', 1, max, nothing)

    while (1):
        try:
            ksize = cv2.getTrackbarPos('param', 'GRADIENT')
            if ksize < 1:
                ksize = 1
            kernel = np.ones((ksize, ksize), np.uint8)
            GRADIENT_img =cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)
            cv2.imshow('GRADIENT', GRADIENT_img)
            k = cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k == 27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize, GRADIENT_img
            elif cv2.getWindowProperty('GRADIENT', cv2.WND_PROP_AUTOSIZE) < 1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break



# 顶帽运算
def TOPHAT_param(img, max):
    # 创建一个带trackbar的窗口
    cv2.namedWindow('TOPHAT')
    cv2.createTrackbar('param', 'TOPHAT', 1, max, nothing)

    while (1):
        try:
            ksize = cv2.getTrackbarPos('param', 'TOPHAT')
            if ksize < 1:
                ksize = 1
            kernel = np.ones((ksize, ksize), np.uint8)
            TOPHAT_img =cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)
            cv2.imshow('TOPHAT', TOPHAT_img)
            k = cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k == 27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize, TOPHAT_img
            elif cv2.getWindowProperty('TOPHAT', cv2.WND_PROP_AUTOSIZE) < 1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break



# 黑帽运算
def BLACKHAT_param(img, max):
    # 创建一个带trackbar的窗口
    cv2.namedWindow('BLACKHAT')
    cv2.createTrackbar('param', 'BLACKHAT', 1, max, nothing)

    while (1):
        try:
            ksize = cv2.getTrackbarPos('param', 'BLACKHAT')
            if ksize < 1:
                ksize = 1
            kernel = np.ones((ksize, ksize), np.uint8)
            BLACKHAT_img =cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)
            cv2.imshow('BLACKHAT', BLACKHAT_img)
            k = cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k == 27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize, BLACKHAT_img
            elif cv2.getWindowProperty('BLACKHAT', cv2.WND_PROP_AUTOSIZE) < 1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break


#canny参数输入窗口
def canny_params(img):

    #创建一个带trackbar的窗口
    cv2.namedWindow('canny')
    cv2.createTrackbar('min','canny',0,255,nothing)
    cv2.createTrackbar('max', 'canny', 0, 255, nothing)
    while(1):
        try:
            min=cv2.getTrackbarPos('min','canny')
            max=cv2.getTrackbarPos('max','canny')
            canny_img=cv2.Canny(img,min,max)
            cv2.imshow('canny',canny_img)
            k=cv2.waitKey(1)
            if k==27:
                cv2.destroyAllWindows()
                return min, max,canny_img
                break
            elif cv2.getWindowProperty('canny',cv2.WND_PROP_AUTOSIZE)<1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break


#Laplacian参数输入窗口
def Laplacian_param(img,max):

    #创建一个带trackbar的窗口
    cv2.namedWindow('Laplacian')
    cv2.createTrackbar('param','Laplacian',1,max,nothing)

    while(1):
        try:
            ksize=cv2.getTrackbarPos('param','Laplacian')
            ksize=2*ksize-1
            if ksize < 1:
                ksize = 1
            lapla=cv2.Laplacian(img,cv2.CV_16S, ksize=ksize)
            Laplacian_img=cv2.convertScaleAbs(lapla)
            cv2.imshow('Laplacian',Laplacian_img)
            k=cv2.waitKey(1)

            # esc的ASCII码是27，回车的是13，换行10，空格32
            if k==27:
                cv2.destroyAllWindows()

                # 返回核大小和处理后的图片
                return ksize,Laplacian_img
            elif cv2.getWindowProperty('Laplacian',cv2.WND_PROP_AUTOSIZE)<1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break



#log参数输入窗口
def log_params(img):

    #创建一个带trackbar的窗口
    cv2.namedWindow('log')
    cv2.createTrackbar('gauss','log',0,10,nothing)
    cv2.createTrackbar('lapla', 'log', 0, 10, nothing)
    while(1):
        try:
            gauss=cv2.getTrackbarPos('gauss','log')
            gauss = 2 * gauss - 1
            Gaussian_img = cv2.GaussianBlur(img, (gauss, gauss), 1)

            lapla=cv2.getTrackbarPos('lapla','log')
            lapla = 2 * lapla - 1
            if lapla < 1:
                lapla = 1
            lapla_img = cv2.Laplacian(img, cv2.CV_16S, ksize=lapla)

            log_img = cv2.convertScaleAbs(lapla_img)
            cv2.imshow('log',log_img)
            k=cv2.waitKey(1)
            if k==27:
                cv2.destroyAllWindows()
                return gauss, lapla,log_img
                break
            elif cv2.getWindowProperty('log',cv2.WND_PROP_AUTOSIZE)<1:
                cv2.destroyAllWindows()
                break
        except Exception as e:
            show_mes(str(e))
            break


#log参数输入窗口
def circle_params(img,img_col):
    #创建一个带trackbar的窗口
    cv2.namedWindow('circle')
    #dp为检测内侧圆心的累加器图像的分辨率于输入图像之比的倒数，如dp=1，累加器和输入图像具有相同的分辨率，如果dp=2，累计器便有输入图像一半那么大的宽度和高度
    # cv2.createTrackbar('dp','circle',1,5,nothing)
    #minDist表示两个圆之间圆心的最小距离
    cv2.createTrackbar('minDist', 'circle', 40, 100, nothing)
    #param1有默认值100，它是method设置的检测方法的对应的参数，对当前唯一的方法霍夫梯度法cv2.HOUGH_GRADIENT，它表示传递给canny边缘检测算子的高阈值，而低阈值为高阈值的一半
    cv2.createTrackbar('param1', 'circle', 100, 255, nothing)
    #param2有默认值100，它是method设置的检测方法的对应的参数，对当前唯一的方法霍夫梯度法cv2.HOUGH_GRADIENT，它表示在检测阶段圆心的累加器阈值，它越小，就越可以检测到更多根本不存在的圆，而它越大的话，能通过检测的圆就更加接近完美的圆形了
    cv2.createTrackbar('param2', 'circle', 11, 200, nothing)
    #minRadius有默认值0，圆半径的最小值
    cv2.createTrackbar('minRadius', 'circle', 8, 200, nothing)
    #maxRadius有默认值0，圆半径的最大值
    cv2.createTrackbar('maxRadius', 'circle', 20, 200, nothing)

    while(1):
        try:
            img_cril = img_col.copy()
            # dp = cv2.getTrackbarPos('dp', 'circle')
            # if dp < 1:
            #     dp = 1
            minDist = cv2.getTrackbarPos('minDist', 'circle')
            if minDist < 1:
                minDist = 1
            param1 = cv2.getTrackbarPos('param1', 'circle')
            if param1 < 1:
                param1 = 1
            param2 = cv2.getTrackbarPos('param2', 'circle')

            minRadius = cv2.getTrackbarPos('minRadius', 'circle')
            if minRadius < 1:
                minRadius = 1
            maxRadius = cv2.getTrackbarPos('maxRadius', 'circle')
            if maxRadius < 1:
                maxRadius = 1
            circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, minDist, param1=param1, param2=param2, minRadius=int(minRadius), maxRadius=int(maxRadius))

            #判断是否检测到圆，如果没有circles的类型为<class 'NoneType'>
            if str(type(circles))=="<class 'NoneType'>":
                cv2.imshow('circle', img_cril)
                k = cv2.waitKey(1)
                if k == 27:
                    cv2.destroyAllWindows()
                    break
                elif cv2.getWindowProperty('circle', cv2.WND_PROP_AUTOSIZE) < 1:
                    cv2.destroyAllWindows()
                    break
            else:
                circles = np.uint16(np.around(circles))
                for i in circles[0, :]:
                    cv2.circle(img_cril, (i[0], i[1]), i[2], (0, 0, 255), 2)
                cv2.imshow('circle', img_cril)
                k = cv2.waitKey(1)
                if k == 27:
                    cv2.destroyAllWindows()
                    return img_cril, param1, param2, minRadius, minDist, maxRadius
                    break
                elif cv2.getWindowProperty('circle', cv2.WND_PROP_AUTOSIZE) < 1:
                    cv2.destroyAllWindows()
                    break

        except Exception as e:
            show_mes("圆检测需要在灰度模式下进行！"+str(e))
            break

#line参数输入窗口
def line_params(img,img_col):
    #创建一个带trackbar的窗口
    cv2.namedWindow('line')

    #是经过某一点曲线的数量的阈值，超过这个阈值，表示这个点所代表的参数对（rho，theta）在原图像中为一条直线
    cv2.createTrackbar('threshold', 'line', 100, 250, nothing)

    #线的最短长度，比这个长度短都被忽略
    cv2.createTrackbar('minlinelength', 'line', 100, 200, nothing)

    #两条线之间的最大间隔，如果小于此值，则这两天直线会当成一条直线
    cv2.createTrackbar('maxlinegap', 'line', 10, 200, nothing)

    while(1):
        try:
            img_line = img_col.copy()
            threshold = cv2.getTrackbarPos('threshold', 'line')
            if threshold < 1:
                threshold = 1

            minlinelength = cv2.getTrackbarPos('minlinelength', 'line')
            if minlinelength < 1:
                minlinelength = 1
            maxlinegap = cv2.getTrackbarPos('maxlinegap', 'line')
            if maxlinegap < 1:
                maxlinegap = 1

            lines = cv2.HoughLinesP(img,1, np.pi/180,threshold, minlinelength,maxlinegap)

            # 判断是否检测到线，如果没有circles的类型为<class 'NoneType'>
            if str(type(lines)) == "<class 'NoneType'>":
                cv2.imshow('line', img_line)
                k = cv2.waitKey(1)
                if k == 27:
                    cv2.destroyAllWindows()
                    break
                elif cv2.getWindowProperty('line', cv2.WND_PROP_AUTOSIZE) < 1:
                    cv2.destroyAllWindows()
                    break
            else:

                for i in lines:

                    #HoughLinesP，返回值就是直线的起点和终点
                    x1,y1,x2,y2=i[0]
                    cv2.line(img_line,(x1,y1),(x2,y2), (0, 255, 255), 2)
                cv2.imshow('line',img_line)

                k = cv2.waitKey(1)
                if k == 27:
                    cv2.destroyAllWindows()
                    return img_line,threshold,minlinelength,maxlinegap
                    break
                elif cv2.getWindowProperty('line', cv2.WND_PROP_AUTOSIZE) < 1:
                    cv2.destroyAllWindows()
                    break
        except Exception as e:
            show_mes("首先对图片进行轮廓检测，再进行直线检测！"+str(e))
            break